home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / games / IndiZone / gold / doerMethods.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  25.8 KB  |  979 lines

  1. /*
  2.  * The original copyright owners of the accompanying source code files have
  3.  * agreed to place such code into the public domain.  Accordingly, anyone
  4.  * who receives or obtains a copy of such source code is freely entitled to
  5.  * reproduce, use and otherwise exploit such code (including the right to
  6.  * make derivative works), at his/her own risk and expense, without any
  7.  * obligation or liability to the original copyright owners.
  8.  *
  9.  * We would appreciate (but do not require) that the following message be
  10.  * included in any derivative works:
  11.  *
  12.  * "Portions of this program were developed by Peter Broadwell, Rob Myers
  13.  * and Robin Schaufler while working in Silicon Valley."
  14.  *
  15.  * The accompanying source code files and related documentation materials
  16.  * are distributed on an "AS IS" basis, without any warranties or
  17.  * guarantees of any kind.  All implied warranties, including the implied
  18.  * warranties of merchantability and of fitness for any particular purpose,
  19.  * are expressly disclaimed.
  20.  */
  21. #include <stdio.h>
  22. #include <ctype.h>
  23. #include "gl.h"
  24. #include "math.h"
  25. #include "geom.h"
  26. #include "colors.h"
  27. #include "objIds.h"
  28. #include "class.h"
  29. #include "classIds.h"
  30. #include "selectors.h"
  31. #include "mbox.h"
  32. #include "individual.h"
  33. #include "behavior.h"
  34. #include "doers.h"
  35. #include "panel.h"
  36. #include "voxel.h"
  37. #include "sounds.h"
  38.  
  39. extern individual *us;
  40. extern individual *curIndiv;
  41. extern individual ghostTemplate;
  42. extern long masterClock;
  43.  
  44. extern subscr *findvars();
  45. extern behavior chameleonTemplate;
  46. extern behavior expanderTemplate;
  47. extern behavior advancerTemplate;
  48. extern behavior surfDieTemplate;
  49. extern behavior wideyeTemplate;
  50. extern behavior faderTemplate;
  51.  
  52. #define PI 3.14159265358979323844
  53. #define DEG(x) ((float)x*(float)180/PI)
  54. #define RAD(x) ((float)x*PI/(float)180)
  55.  
  56.  
  57.     /*
  58.      *  wiggle the target individual
  59.      */
  60.     behavior *
  61. wiggle(self, argtype, target)
  62.     behavior *self;
  63.     int argtype;
  64.     register individual *target;
  65. {
  66.     register wigglerVars *vars;
  67.     register model *m;
  68.  
  69.     if (vars = (wigglerVars *)target->curVars) {
  70.     vars->angle = vars->magnitude
  71.         * sin(RAD(vars->wiggleClock))
  72.         * cos(5*RAD(vars->wiggleClock));
  73.     vars->wiggleClock+=6;
  74.  
  75.         /* rotate body and tail by opposite angles */
  76.         /* body is first model segment */
  77.     if (m = target->descr) {
  78.         m->rotation.z = -1 * vars->angle;
  79.  
  80.         /* tail is next model segment */
  81.         if (m = m->next)
  82.         m->rotation.z = 7 * vars->angle;
  83.     }
  84.     }
  85.     else fprintf(stderr, "wiggle: can't find instance variables\n");
  86.  
  87.     return self;
  88. }
  89.  
  90. editWiggler(self, argtype, him)
  91.     behavior *self;        /* WIGGLER */
  92.     int argtype;
  93.     individual *him;        /* edit wiggler vars for him */
  94. {
  95.     panel *p;
  96.     rectangle r;
  97.     wigglerVars *wentry;
  98.  
  99.     extern panel *makePanel();
  100.  
  101.     wentry = (wigglerVars *)him->curVars;
  102.  
  103.     p = (panel *)him->controls;
  104.     setrect(&r, 10, getHighwater(p), 0,0);
  105.     p = p->kids = makePanel(p->kids, p, &r, NULL);
  106.     initVanillaVal(p, 10, 160, &wentry->magnitude, "Flop");
  107.     addBHMenu(self,p,"WIGGLER BEHAVIOR");
  108.     bumpHighwater(p->area.extent.y + 10);
  109. }
  110.  
  111.     /*
  112.      *  advance the target individual around his circle
  113.      */
  114.     behavior *
  115. advanceTo(self, argtype, target)
  116.     behavior *self;
  117.     int argtype;
  118.     register individual *target;
  119. {
  120.     register circlerVars *vars;
  121.  
  122.     if (vars = (circlerVars *)target->curVars) {
  123.     target->position.x = vars->tether * sin(RAD(vars->circleClock))
  124.                             + vars->stake.x;
  125.     target->position.y = vars->tether * cos(RAD(vars->circleClock))
  126.                             + vars->stake.y;
  127.     target->position.z = vars->tether * 0.15
  128.                   * sin(RAD(vars->circleClock*PI)) + vars->stake.z;
  129.  
  130.     vars->circleClock += vars->circleIncr;
  131.  
  132. /*    Msg(target, MOVE, NOARG, NULL); /* */
  133.     }
  134.     else
  135.     fprintf(stderr, "advanceTo: can't find instance variables\n");
  136.  
  137.     return self;
  138. }
  139.  
  140.     /*
  141.      *  aquire colors from outer space
  142.      */
  143.     behavior *
  144. altercolor(self, argtype, target)
  145.     behavior *self;
  146.     int argtype;
  147.     register individual *target;
  148. {
  149.     register model *m;
  150.     static rgbcolor newhue;
  151.     register chameleonVars *vars;
  152.  
  153.     if (vars = (chameleonVars *)target->curVars) {
  154.     if (m = target->descr) {
  155.         if (vars->inited == FALSE) {
  156.         gmcolor(m->color, &newhue.r, &newhue.g, &newhue.b);
  157.         vars->nativeColor.r = newhue.r;
  158.         vars->nativeColor.g = newhue.g;
  159.         vars->nativeColor.b = newhue.b;
  160.         vars->inited = TRUE;
  161.         }
  162.         if (vars->influenced == TRUE) {
  163.         mapcaller(m->color, vars->importColor.r,
  164.                    vars->importColor.g,
  165.                    vars->importColor.b);
  166.         vars->influenced = FALSE;
  167.         }
  168.         else {
  169.         mapcaller(m->color, vars->nativeColor.r,
  170.                    vars->nativeColor.g,
  171.                    vars->nativeColor.b);
  172.         unsubscribe(&chameleonTemplate, target);
  173.         }
  174.     }
  175.     }
  176.  
  177.     return self;
  178. }
  179.  
  180. editColorizer(self, argtype, him)
  181.     behavior *self;        /* COLORIZER */
  182.     int argtype;
  183.     individual *him;        /* edit colorizer vars for him */
  184. {
  185.     panel *p;
  186.     rectangle r;
  187.     colorizerVars *centry;
  188.  
  189.     extern panel *makePanel();
  190.  
  191.     centry = (colorizerVars *)him->curVars;
  192.  
  193.     p = (panel *)him->controls;
  194.     setrect(&r, 10, getHighwater(p), 200,getheight()+10);
  195.     p = p->kids = makePanel(p->kids, p, &r, NULL);
  196.     addBHMenu(self,p,"COLORIZER BEHAVIOR");
  197.     bumpHighwater(p->area.extent.y + 10);
  198. }
  199.  
  200.     /*
  201.      *  export color to neighbors
  202.      */
  203.     behavior *
  204. exportcolor(self, argtype, target)
  205.     behavior *self;
  206.     int argtype;
  207.     register individual *target;
  208. {
  209.     colorizerVars *myvars;
  210.     chameleonVars *hisvars;
  211.     mailbox *vox;
  212.     inst *him;
  213.     register subscr *sentry;
  214.  
  215.     if (myvars = (colorizerVars *)target->curVars) {
  216.     if ((sentry = findvars(target, VOXEL)) == NULL) {
  217.         fprintf(stderr,"exportcolor: can't find my vox\n");
  218.         return NULL;
  219.     }
  220.     vox = (mailbox *)sentry->member;
  221.     for (sentry = vox->subscribers; sentry; sentry=sentry->next) {
  222.         him = sentry->member;
  223.         if ((hisvars = (chameleonVars *)findvars(him, CHAMELEON)) == NULL) {
  224.         subscribe(&chameleonTemplate, him);
  225.         hisvars = (chameleonVars *)findvars(him, CHAMELEON);
  226.         }
  227.         if (hisvars) {
  228.         hisvars->importColor.r = myvars->exportColor.r;
  229.         hisvars->importColor.g = myvars->exportColor.g;
  230.         hisvars->importColor.b = myvars->exportColor.b;
  231.         hisvars->influenced = TRUE;
  232.         }
  233.         else
  234.         fprintf(stderr,"exportcolor: can't get chameleonVars\n");
  235.     }
  236.     }
  237.  
  238.     return self;
  239. }
  240.  
  241.     /*
  242.      *  general purpose advance according to acceleration and velocity
  243.      */
  244.     behavior *
  245. advance(self, argtype, target)
  246.     behavior *self;
  247.     int argtype;
  248.     register individual *target;
  249. {
  250.     target->velocity.x += target->acceleration.x;
  251.     target->velocity.y += target->acceleration.y;
  252.     target->velocity.z += target->acceleration.z;
  253.  
  254.     target->position.x += target->velocity.x;
  255.     target->position.y += target->velocity.y;
  256.     target->position.z += target->velocity.z;
  257.  
  258.     return self;
  259. }
  260.  
  261.     /*
  262.      *  die if height is at or above surface
  263.      */
  264.     surfaceDie *
  265. dieAtSurface(self, argtype, target)
  266.     surfaceDie *self;
  267.     int argtype;
  268.     register individual *target;
  269. {
  270.     if (target->position.z >= self->surface) {
  271.     unsubscribe(us, target);
  272.     Msg(target, FREE, NOARG, NULL);    /* get rid of all nested memory */
  273.  
  274.     return NULL;
  275.     }
  276.  
  277.     return self;
  278. }
  279.  
  280.     /*
  281.      *  expand up to scaleMax
  282.      */
  283.     behavior *
  284. expandScale(self, argtype, target)
  285.     behavior *self;
  286.     int argtype;
  287.     register individual *target;
  288. {
  289.     register expanderVars *vars;
  290.  
  291.     if (vars = (expanderVars *)target->curVars) {
  292.     if (target->scale < vars->scaleMax)
  293.         target->scale *= vars->scaleIncr;
  294.     if (target->scale > vars->scaleMax) {
  295.         target->scale = vars->scaleMax;
  296.         unsubscribe(self, target);
  297.     }
  298.     }
  299.  
  300.     return self;
  301. }
  302.  
  303.     /*
  304.      *  lay calls getMate in order to get a mate for the girl.
  305.      */
  306.     individual *
  307. getMate(girl, femVars, vox)
  308.     individual *girl;
  309.     femaleVars *femVars;
  310.     mailbox *vox;
  311. {
  312.     individual *him;
  313.     maleVars *hisVars = NULL;
  314.     subscr *sentry;
  315.     int population, species;
  316.  
  317.     if (femVars->mate) {
  318.         for (sentry = vox->subscribers; sentry; sentry=sentry->next) {
  319.         if (femVars->mate == sentry->member)
  320.         return NULL;        /* still mating */
  321.     }    /* done mating, so lay them eggs */
  322.     him = (individual *)femVars->mate;
  323.     femVars->mate = NULL;
  324.     return him;
  325.     } else {    /* girl has no mate, so look for one. */
  326.         /* first, exercise population growth control */
  327.     if (!girl->them.me.myClass) return NULL;
  328.     species = girl->them.me.myClass->classId;
  329.     population = 1;
  330.     for (sentry = us->them.subscribers; sentry; sentry=sentry->next) {
  331.         if (sentry->member && sentry->member->myClass
  332.         &&  sentry->member->myClass->classId == species) {
  333.         if (++population > femVars->max_population)
  334.             return NULL;
  335.         }
  336.     }
  337.         /* now look for a mate */
  338.     for (sentry = vox->subscribers; sentry; sentry=sentry->next) {
  339.         him = (individual *)sentry->member;
  340.         /* if mature girl meets mature male of same species */
  341.         if ((hisVars = (maleVars *)findvars(him, MALE))
  342.         && hisVars->interest > 0
  343.         && ! findvars(him, EXPANDER)
  344.         &&  him->them.me.myClass->classId == girl->them.me.myClass->classId)
  345.         {
  346.         break;
  347.         }
  348.     }
  349.     if (sentry) {
  350.         femVars->mate = sentry->member;
  351.         hisVars->interest = hisVars->min_int;
  352.     }
  353.     return NULL;
  354.     }
  355. }
  356.  
  357.     /*
  358.      *  if a male is nearby, lay eggs.
  359.      */
  360.     behavior *
  361. lay(self, argtype, girl)
  362.     behavior *self;
  363.     int argtype;
  364.     register individual *girl;
  365. {
  366.     mailbox *vox;
  367.     individual *mate, *him, *ovum;
  368.     extern individual eggTemplate, metamorphTemplate, *us;
  369.     register subscr *sentry;
  370.     metamorphVars *initMeta;
  371.     femaleVars *femVars = NULL;
  372.     int i, num_of_eggs = 3, n_girls = 2, n_boys = 1;
  373.  
  374.     if (findvars(girl, EXPANDER))    /* immature */
  375.     return self;
  376.     if ((sentry = findvars(girl, VOXEL)) == NULL) {
  377.     fprintf(stderr,"lay: can't find my voxel\n");
  378.     return self;
  379.     }
  380.     vox = (mailbox *)sentry->member;
  381.     if (! (femVars = (femaleVars *)girl->curVars)) {
  382.     fprintf(stderr,"lay: can't find my curvars\n");
  383.     return self;
  384.     }
  385.     if ((mate = getMate(girl, femVars, vox)) == NULL)
  386.     return self;
  387.     
  388.     /*
  389.      *  If mate is dead, we can't clone him to make boy babies.
  390.      */
  391.     n_girls = femVars->n_girls;
  392.     n_boys  = femVars->n_boys;
  393.     for (sentry = us->them.subscribers; sentry; sentry = sentry->next)
  394.     if (sentry->member == (inst *)mate)
  395.         break;
  396.     if (!sentry) {
  397.     n_girls += n_boys;
  398.     n_boys = 0;
  399.     }
  400.     num_of_eggs = n_girls + n_boys;
  401.  
  402.         /*
  403.          *  Only get here if mate has left voxel.
  404.          *  should check "us" to see if he is alive before
  405.          *  cloning him for male eggs.
  406.          */
  407.  
  408.         /*
  409.          *  0 <= num_of_eggs <= max_eggs.
  410.          */
  411.     for (i=1; i<=num_of_eggs; i++) {
  412.     him = (individual *)clone(i<=n_girls ? girl : mate);
  413.     Msg(him, INIT, NOARG, NULL);
  414.  
  415. /*******************
  416.          * find a bad egg who exceeds the maximum number of
  417.          * available model indices;
  418.          * blow him away and stop making more of em
  419.     if (TRUE == badModelIndex(him->descr, him)) {
  420.         printf("lay: breaking out due to bad model index at egg %d\n",i);
  421.         Msg(him, FREE, NOARG, NULL);
  422.         break;
  423.     }
  424. /*************/
  425.  
  426.     him->flags &= ~PICKED;
  427.     him->scale = (long)(0.43 * i) + 2;
  428.  
  429.     sentry = him->them.subscribers;    /* for now, forget subscribers */
  430.     him->them.subscribers = NULL;
  431.     sentry = him->them.subscribedTo;
  432.     him->them.subscribedTo = NULL;
  433.     for (; sentry; sentry = sentry->next) {
  434.         if(isSuper(sentry->member, VOXEL)) continue;
  435.         halfsubscr(sentry->member, him);
  436.         if(isSuper(sentry->member, BEHAVIOR)
  437.         && ((behavior *)sentry->member)->varsize) {
  438.         bcopy(&sentry->member, &him->them.subscribedTo->member,
  439.               ((behavior *)sentry->member)->varsize - sizeof(char *));
  440.         if(isSuper(sentry->member, SWERVER)) {
  441.             swerverVars *swerVars =
  442.             (swerverVars *)him->them.subscribedTo;
  443.             /****
  444.             swerVars->maxvelocity.x +=
  445.             (odd(i) ? 1 : -1) *
  446.             (swerVars->maxvelocity.x / (3 + (i>>1)));
  447.             swerVars->maxvelocity.y +=
  448.             (odd(i) ? 1 : -1) *
  449.             (swerVars->maxvelocity.y / (5 + (i>>1)));
  450.             swerVars->maxvelocity.z +=
  451.             (odd(i) ? 1 : -1) *
  452.             (swerVars->maxvelocity.z / (1 + (i>>1)));
  453.             *****/
  454.         }
  455.         }
  456.     }
  457.     him->position.x += 50 * i * (odd(i) ? 1 : -1);
  458.     him->position.y += 100 * i * (odd(i>>1) ? 1 : -1);
  459.     him->position.z += 50 * i * (odd(i>>1) ? -1 : 1);
  460.     him->heading.x *= (odd(i) ? 1 : -1);
  461.     him->heading.y *= (odd(i>>1) ? 1 : -1);
  462.     him->heading.z *= (odd(i>>1) ? -1 : 1);
  463.  
  464.     ovum = (individual *)clone(&eggTemplate);
  465.     subscribe(&metamorphTemplate, ovum);
  466.     initMeta = (metamorphVars *)ovum->them.subscribedTo;
  467.     initMeta->embryo = him;
  468.     initMeta->alarm = 20 * i;
  469.     ovum->position = him->position;
  470.     newVoxPosition(vox, &ovum->position, ovum);
  471.     subscribe(us, ovum);
  472.     Msg(ovum, INIT, 0, NULL);
  473.     }
  474.     doSound(LAY_EGGS);
  475.     return self;
  476. }
  477.  
  478. editFemale(self, argtype, him)
  479.     behavior *self;        /* FEMALE */
  480.     int argtype;
  481.     individual *him;        /* edit female vars for him */
  482. {
  483.     panel *p;
  484.     rectangle r;
  485.     femaleVars *fentry;
  486.  
  487.     extern panel *makePanel();
  488.  
  489.     fentry = (femaleVars *)him->curVars;
  490.  
  491.     p = (panel *)him->controls;
  492.     setrect(&r, 10, getHighwater(p), 0,0);
  493.     p = p->kids = makePanel(p->kids, p, &r, NULL);
  494.     initVanillaVal(p, 0, 3, &fentry->n_girls, "Girl Eggs");
  495.     initVanillaVal(p, 0, 3, &fentry->n_boys,  "Boy Eggs");
  496.     initVanillaVal(p, 3, 5, &fentry->max_population,  "Cozy");
  497.     /* initVanillaVal(p, 3, 6, &fentry->max_population,  "Cozy"); /**/
  498.     addBHMenu(self,p,"FEMALE BEHAVIOR");
  499.     bumpHighwater(p->area.extent.y + 10);
  500. }
  501.  
  502.     /*
  503.      *  used by fertilize in conjunction with voxSee,
  504.      *  such that for each voxel in target's line of sight,
  505.      *  chaseGirl gets called.
  506.      */
  507. chaseGirl(vox, target, path)
  508.     voxel *vox;
  509.     individual *target;
  510.     char *path;        /* pointing to char that got me to vox */
  511. {
  512.     subscr *sentry = NULL;
  513.     maleVars *hisVars = NULL;
  514.     individual *girl;
  515.     double ov_squ = 1, nv_squ = 1;    /* how fast am I currently going? */
  516.     point *t_vel;
  517.     point vel_to_girl;
  518.  
  519.     if (! target->them.me.myClass)
  520.     return HALT;
  521.  
  522.     hisVars = (maleVars *)target->curVars;
  523.  
  524.     /* search all individuals in vox */
  525.     for (sentry = vox->mbox.subscribers;
  526.      sentry;
  527.      sentry = sentry->next)
  528.     {
  529.     girl = (individual *)sentry->member;
  530.     if (!girl->them.me.myClass) continue;
  531.         /*
  532.          *  upon finding a mature female of the same species,
  533.          *  head towards her.
  534.          */
  535.     if (findvars(girl, FEMALE)
  536.     && ! findvars(girl, EXPANDER)
  537.     &&  target->them.me.myClass->classId == girl->them.me.myClass->classId)
  538.         {
  539. /*          drawVoxel(vox);        /* for debugging */
  540. #define FUD 16
  541.  
  542. #define ROBS_SWIM
  543. #ifdef ROBS_SWIM
  544.         vel_to_girl.x = girl->position.x - target->position.x;
  545.         vel_to_girl.y = girl->position.y - target->position.y;
  546.         vel_to_girl.z = girl->position.z - target->position.z;
  547.         /* normalize and set heading to point at girl */
  548.         vtoh(&target->heading, &vel_to_girl);
  549. #else /* ROBS_SWIM */
  550.         t_vel = &target->velocity;
  551.         ov_squ = (double) (
  552.                  t_vel->x * t_vel->x +
  553.                  t_vel->y * t_vel->y +
  554.                  t_vel->z * t_vel->z + FUD);
  555.         t_vel->x = girl->position.x - target->position.x;
  556.         t_vel->y = girl->position.y - target->position.y;
  557.         t_vel->z = girl->position.z - target->position.z;
  558.         nv_squ = (double) (
  559.                  t_vel->x * t_vel->x +
  560.                  t_vel->y * t_vel->y +
  561.                  t_vel->z * t_vel->z);
  562.         if (nv_squ > ov_squ) {
  563.         ov_squ = sqrt(fabs(ov_squ));
  564.         nv_squ = sqrt(fabs(nv_squ));
  565.         t_vel->x = (t_vel->x * (int)ov_squ) / (int)nv_squ;
  566.         t_vel->y = (t_vel->y * (int)ov_squ) / (int)nv_squ;
  567.         t_vel->z = (t_vel->z * (int)ov_squ) / (int)nv_squ;
  568.         }
  569. #endif /* ROBS_SWIM */
  570.         hisVars->flags |= FOUND_THIS_TIC;
  571.         return HALT;
  572.     }
  573.     }
  574.     if (isdigit(path[1])
  575.     &&  hisVars->interest < ((int)path[1]&0xf))
  576.         return HALT;
  577.  
  578.     return CONTINUE;
  579. }
  580.  
  581.     /*
  582.      *  if a female is in the same voxel, fertilize eggs.
  583.      *  if a female is in sight, chase her!
  584.      */
  585.     behavior *
  586. fertilize(self, argtype, target)
  587.     behavior *self;
  588.     int argtype;
  589.     register individual *target;
  590. {
  591.     subscr *entry;
  592.     maleVars *hisEntry;
  593.     wideyeVars *eyevars;
  594.     voxel *vox;
  595.     static char chasePath[] =
  596.     "f1f2furddlluu3RDfurddlluu4RDfurddlluuurrrddddlllluuuu5RRDDfurddlluuurrrddddlllluuuu";
  597. /*    static char chasePath[] = "FfffurddlluuRDfurddlluu"; */
  598.  
  599.     /*
  600.      *  for each voxel in line of sight within a given distance,
  601.      *      if a subscriber in the voxel is the same class as target
  602.      *      and is female,
  603.      *          determine point where paths intersect.
  604.      *          if that point is ahead of target
  605.      *              determine time when she should be there.
  606.      *              adjust magnitude of velocity to try to arrive at
  607.      *              the same time.
  608.      *          else
  609.      *              pick a point on her path and aim for it, based
  610.      *              on relative slopes of female's and target's paths.
  611.      */
  612.     hisEntry = (maleVars *)target->curVars;
  613.     if (hisEntry->flags & FOUND_THIS_TIC)
  614.     hisEntry->flags = FOUND_LAST_TIC;
  615.     else
  616.     hisEntry->flags = 0;
  617.     if (++hisEntry->tics > hisEntry->rate) {
  618.     hisEntry->tics = 0;
  619.     if (hisEntry->interest < hisEntry->max_int) {
  620.         hisEntry->interest++;
  621.     }
  622.     }
  623.     if (hisEntry->interest <= 0)
  624.     return self;
  625.     entry = findvars(target, VOXEL);
  626.     if (! entry) {
  627.     fprintf(stderr, "fertilize: can't find voxel for %x, class %d\n",
  628.         target, target->them.me.myClass->classId);
  629.     return self;
  630.     }
  631.     vox = (voxel *)entry->member;
  632.  
  633.     voxTurtle(vox, chasePath, &target->delta, chaseGirl, target);
  634.  
  635.     /* if found mate this tic but not last tic, eyes grow wider */
  636.     eyevars = (wideyeVars *)findvars(target, WIDEYE);
  637.     if (hisEntry->flags == FOUND_THIS_TIC) {
  638.     if (eyevars == NULL) {
  639.         subscribe(&wideyeTemplate, target);
  640.         eyevars = (wideyeVars *)findvars(target, WIDEYE);
  641.     }
  642.     }
  643.     if (hisEntry->flags & FOUND_THIS_TIC && eyevars) {
  644.     eyevars->influenced = TRUE;
  645.     eyevars->scalefactor = hisEntry->eyescale;
  646.     }
  647.  
  648.     return self;
  649. }
  650.  
  651. editMale(self, argtype, him)
  652.     behavior *self;        /* MALE */
  653.     int argtype;
  654.     individual *him;        /* edit male vars for him */
  655. {
  656.     panel *p;
  657.     rectangle r;
  658.     maleVars *mentry;
  659.  
  660.     extern panel *makePanel();
  661.  
  662.     mentry = (maleVars *)him->curVars;
  663.  
  664.     p = (panel *)him->controls;
  665.     setrect(&r, 10, getHighwater(p), 0,0);
  666.     p = p->kids = makePanel(p->kids, p, &r, NULL);
  667.     initVanillaVal(p, mentry->min_int, mentry->max_int,
  668.                   &mentry->interest, "Lust");
  669.     initVanillaVal(p, 100, 5, &mentry->rate, "Recovery");
  670.     initVanillaValf(p, 1.5, 3.0, &mentry->eyescale, "Thrill");
  671.     addBHMenu(self,p,"MALE BEHAVIOR");
  672.     bumpHighwater(p->area.extent.y + 10);
  673. }
  674.  
  675.     /*
  676.      *  after some time, change one individual into another.
  677.      */
  678.     behavior *
  679. altershape(meta, argtype, oldform)
  680.     behavior *meta;
  681.     int argtype;
  682.     register individual *oldform;
  683. {
  684.     register individual *hatchling;
  685.     expanderVars *vars;
  686.     register subscr *sentry, *nentry;
  687.     metamorphVars *mentry;
  688.     inst *vox;
  689.  
  690.     if(! (mentry = (metamorphVars *)findvars(oldform, METAMORPH)) )
  691.     return meta;
  692.     if (mentry->clock++ > mentry->alarm) {
  693.     if(! (hatchling = mentry->embryo) )
  694.         return meta;
  695. do_metamorph:    /*  label to key on in adb  */
  696.         /*  find egg's voxel  */
  697.     sentry = findvars(oldform, VOXEL);
  698.     if(sentry)
  699.         vox = sentry->member;
  700.  
  701.         /*
  702.          *  hatchling->subscribers, subscribedTo is just a list
  703.          *  of what had subscribed to mom and what mom had
  704.          *  subscribed to, respectively.
  705.          *  Now hatchling really subscribes.
  706.          */
  707.     for(sentry = hatchling->them.subscribers,
  708.         hatchling->them.subscribers = 0;
  709.         sentry;
  710.         sentry = nentry)
  711.     {
  712.         nentry = sentry->next;
  713.         subscribe(hatchling, sentry->member);
  714.         gffree(sentry);
  715.     }
  716.     for(sentry = hatchling->them.subscribedTo,
  717.         hatchling->them.subscribedTo = 0;
  718.         sentry;
  719.         sentry = nentry)
  720.     {
  721.         nentry = sentry->next;
  722.         subscribe(sentry->member, hatchling);
  723.         if(isSuper(sentry->member, BEHAVIOR)) {
  724.         bcopy(&sentry->member, &hatchling->them.subscribedTo->member,
  725.               ((behavior *)sentry->member)->varsize - sizeof(char *));
  726.         }
  727.         gffree(sentry);
  728.     }
  729.  
  730.     subscribe(&expanderTemplate, hatchling);
  731.     if (vars = (expanderVars *)hatchling->them.subscribedTo) {
  732.         /* hatchling will expand to size its mother was */
  733.         vars->scaleMax = hatchling->scale;
  734.         vars->scaleIncr = 1.01;
  735.         hatchling->scale *= 0.2;
  736.     }
  737.     if(vox)
  738.         newVoxPosition(vox, &hatchling->position, hatchling);
  739.     else
  740.         printf("altershape: couldn't find voxel for indiv %x\n", oldform);
  741.  
  742. /*    Msg(hatchling, INIT, NOARG, NULL); /* */
  743.  
  744.     hatchling->lastPosition.x = hatchling->position.x;
  745.     hatchling->lastPosition.y = hatchling->position.y;
  746.     hatchling->lastPosition.z = hatchling->position.z;
  747.     Msg(oldform, FREE, NOARG, NULL);
  748.     return NULL;
  749.     }
  750.     return meta;
  751. }
  752.  
  753. #ifdef NOTDEF
  754.     /*
  755.      *  FREEVARS method. Free embryo before freeing metavars.
  756. NEVER CALLED AS FAR AS I CAN TELL --- peter july 15, 1985
  757.      */
  758.     behavior *
  759. freeMetaVars(self, argtype, metavars)
  760.     behavior *self;    /* METAMORPH */
  761.     int argtype;
  762.     metamorphVars *metavars;
  763. {
  764.     Msg(metavars->embryo, FREE, NOARG, NULL);
  765.     gffree(metavars);
  766.     return NULL;
  767. }
  768. #endif /* NOTDEF */
  769.  
  770.     /*
  771.      *  feed calls getDinner in order to get food to feed the feeder.
  772.      */
  773.     individual *
  774. getDinner(feeder, fentry, vox)
  775.     individual *feeder;
  776.     feederVars *fentry;
  777.     mailbox *vox;
  778. {
  779.     register subscr *sentry, *uentry;
  780.     individual *dindin;
  781.     unsigned gender;
  782.     int species, count = 0;
  783. #define NEUTER 0
  784.  
  785.     for (sentry = vox->subscribers; sentry; sentry=sentry->next) {
  786.     dindin = (individual *)sentry->member;
  787.         /* feeder is not his own dinner */
  788.     if (dindin == feeder)
  789.         continue;
  790.         /* if feeder isn't a cannibal, his own species isn't kosher */
  791.     if (!fentry->cannibal
  792.         && dindin->them.me.myClass->classId
  793.         == feeder->them.me.myClass->classId)
  794.         continue;
  795.  
  796.         /* don't eat the last of a gender/species */
  797.         /* HIGH OVERHEAD FOR SOCIAL RESPONSIBILITY! */
  798.     gender = NEUTER;
  799.     if (findvars(dindin, MALE)) gender = MALE;
  800.     else if (findvars(dindin, FEMALE)) gender = FEMALE;
  801.     species = dindin->them.me.myClass->classId;
  802.     for (uentry = us->them.subscribers; uentry; uentry = uentry->next) {
  803.         if (uentry->member != (inst *)dindin
  804.         &&  uentry->member->myClass->classId == species)
  805.         {
  806.         switch (gender) {
  807.         case NEUTER:
  808.             if (count++)
  809.             return dindin;
  810.         case MALE:
  811.             if (findvars(uentry->member, MALE))
  812.             return dindin;
  813.             break;
  814.         case FEMALE:
  815.             if (findvars(uentry->member, FEMALE))
  816.             return dindin;
  817.             break;
  818.         }
  819.         }    /* if member != dindin && classId == species */
  820.     }   /* for uentry in us->them.subscribers */
  821.     }
  822.     return NULL;
  823. }
  824.  
  825.     /*
  826.      *  if feeder is in the vicinity of food, feed it.
  827.      */
  828.     behavior *
  829. feed(self, argtype, feeder)
  830.     behavior *self;
  831.     int argtype;
  832.     individual *feeder;
  833. {
  834.     mailbox *vox;
  835.     register subscr *sentry;
  836.     expanderVars *bubVars;
  837.     feederVars *fentry;
  838.     individual *dinner, *burp, *makeBub();
  839.  
  840.     if ( !(fentry = (feederVars *)feeder->curVars) )
  841.     return self;
  842.  
  843.     if (++fentry->tics > fentry->rate) {
  844.     fentry->tics = 0;
  845.     if (fentry->interest < fentry->max_int) {
  846.         fentry->interest++;
  847.     }
  848.     }
  849.     if (fentry->interest <= 0)
  850.     return self;
  851.  
  852.     if ((sentry = findvars(feeder, VOXEL)) == NULL) {
  853.     fprintf(stderr,"feed: can't find my voxel\n");
  854.     return self;
  855.     }
  856.     vox = (mailbox *)sentry->member;
  857.     if (dinner = getDinner(feeder, fentry, vox)) {
  858.     expire(dinner, fentry->bubscale);
  859.     fentry->interest = fentry->min_int;
  860.     doSound(MUNCH);
  861.     }
  862.     return self;
  863. }
  864.  
  865. editFeeder(self, argtype, him)
  866.     behavior *self;        /* FEEDER */
  867.     int argtype;
  868.     individual *him;        /* edit feeder vars for him */
  869. {
  870.     panel *p;
  871.     rectangle r;
  872.     feederVars *fentry;
  873.  
  874.     extern panel *makePanel();
  875.  
  876.     fentry = (feederVars *)him->curVars;
  877.  
  878.     p = (panel *)him->controls;
  879.     setrect(&r, 10, getHighwater(p), 0,0);
  880.     p = p->kids = makePanel(p->kids, p, &r, NULL);
  881.     initVanillaVal(p, fentry->min_int, fentry->max_int,
  882.                   &fentry->interest, "Hunger");
  883.     initVanillaVal(p, 100, 5, &fentry->rate, "Metabolism");
  884.     initVanillaValf(p, 50.0, 150.0, &fentry->bubscale, "Satiety");
  885.     addBHMenu(self,p,"FEEDING BEHAVIOR");
  886.     bumpHighwater(p->area.extent.y + 10);
  887. }
  888.  
  889.     /*
  890.      *  widen target's eyes
  891.      */
  892.     behavior *
  893. wideneye(self, argtype, target)
  894.     behavior *self;
  895.     int argtype;
  896.     register individual *target;
  897. {
  898.     register model *m;
  899.     register wideyeVars *vars;
  900.  
  901.     if (vars = (wideyeVars *)findvars(target, WIDEYE)) {
  902.     if (m = target->descr) {
  903.         if (vars->inited == FALSE) {
  904.         /* for each child of m, multiply scale by scalefactor */
  905.         for (m = m->kids; m; m = m->next) {
  906.             m->scale.x *= vars->scalefactor;
  907.             m->scale.y *= vars->scalefactor;
  908.             m->scale.z *= vars->scalefactor;
  909.         }
  910.         vars->inited = TRUE;
  911.         }
  912.         if (vars->influenced == TRUE) {
  913.         vars->influenced = FALSE;
  914.         }
  915.         else {
  916.         /* for each child of m, divide scale by scalefactor */
  917.         for (m = m->kids; m; m = m->next) {
  918.             m->scale.x /= vars->scalefactor;
  919.             m->scale.y /= vars->scalefactor;
  920.             m->scale.z /= vars->scalefactor;
  921.         }
  922.         unsubscribe(&wideyeTemplate, target);
  923.         }
  924.     }
  925.     }
  926.     doSound(BUG_EYE);
  927.     return self;
  928. }
  929.  
  930.     /*
  931.      *  DOIT for faders.
  932.      */
  933.     behavior *
  934. fadeOut(self, argtype, target)
  935.     behavior *self;
  936.     int argtype;
  937.     register individual *target;
  938. {
  939.     faderVars    *vars;
  940.  
  941.     if (vars = (faderVars *)findvars(target, FADER)) {
  942.     if (--vars->age == 0) {
  943.         unsubscribe(us, target);
  944.         unsubscribe(&faderTemplate, target);
  945.         Msg(target, FREE, NOARG, NULL); /* get rid of all nested memory */
  946.  
  947.         return NULL;
  948.     }
  949.     }
  950.  
  951.     return self;
  952. }
  953.  
  954.     /*
  955.      * trail ghosts behind target.
  956.      */
  957.     behavior *
  958. trailGhosts(self, argtype, target)
  959.     behavior *self;
  960.     int argtype;
  961.     register individual *target;
  962. {
  963.     trailGhostVars    *vars;
  964.     individual        *ghost;
  965.  
  966.     if (vars = (trailGhostVars *)findvars(target, TRAIL_GHOSTS)) {
  967.     vars->tic = vars->tic++ % vars->frequency;
  968.     if (!vars->tic) {
  969.         /* drop a new ghost */
  970.         ghost = (individual *)clone(&ghostTemplate);
  971.         Msg(ghost, INIT, NOARG, NULL);
  972.         subscribe(us, ghost);
  973.         ghost->position = target->position;
  974.     }
  975.     }
  976.  
  977.     return self;
  978. }
  979.